// import vnode from "./vnode";

export function patch(oldVnode, newVnode){
    
    if(!oldVnode.sel){  //是不是第一次创建的时候
        // oldVnode = vnode(oldVnode.tagName.toLowerCase(), {}, undefined, oldVnode, undefined);
        // console.log(oldVnode);
        let my_app = createElement(newVnode);
        
        oldVnode.appendChild(my_app);
        return newVnode;
    }
    return compareElm(oldVnode,newVnode);
}

function compareElm(oldVnode,newVnode){   //开始做精细比较
    if(oldVnode.key !== undefined && oldVnode.key === newVnode.key && oldVnode.sel === newVnode.sel){  //精细比较
        if(isAlick(oldVnode,newVnode)){  //判断是否更改
            return oldVnode;
        }
        if(JSON.stringify(oldVnode.data) !== JSON.stringify(newVnode.data)){  //如果data里的属性不一样就将data值重新赋值
            for(var key in newVnode.data){ 
                addElementProps(oldVnode.elm, key, newVnode.data[key])  //开始做属性重新赋值  --TODO-- 后面优化这块考虑只有不一样的属性才重新赋值
            }
        }
        if((newVnode.children === undefined || !newVnode.children.length) && (oldVnode.children === undefined || !oldVnode.children.length)){  //当2个都没有子元素的时候
            if(oldVnode.text !== newVnode.text){
                oldVnode.elm.innerText = newVnode.text;
                oldVnode.text = newVnode.text;
            }
        }else if(newVnode.children === undefined || !newVnode.children.length){  //newVnode不存在子集就直接将老的oldVnode子集为null就行
            oldVnode.elm.innerHtml = null;
            if(oldVnode.text !== newVnode.text){
                oldVnode.elm.innerText = newVnode.text;
                oldVnode.text = newVnode.text;
            }
        }else if(oldVnode.children === undefined || !oldVnode.children.length){  //说明newVnode存在子集
            oldVnode.elm.innerText = '';
            oldVnode.children = newVnode.children;
            newVnode.children.forEach(item => {
                isElement(oldVnode.elm, item);
            });
        }else{  //2个都有子元素
            let new_obj = {...newVnode.children};
            let my_obj = {...new_obj};  //用于子元素按照新元素的顺序排序
            for(var i=0; i<oldVnode.children.length; i++){
                let obj;
                let num = i;
                let is_text = false;  //判断子元素是不是光是文字，不是元素
                for(var key in new_obj){
                    if(oldVnode.children[i].key === undefined && oldVnode.children[i].sel === undefined){  //不是dom元素
                        is_text = true;
                        oldVnode.elm.removeChild(oldVnode.elm.childNodes[i])
                        oldVnode.children.splice(i,1);
                        i--;
                        break;
                    }else if(oldVnode.children[i].key === new_obj[key].key){ //如果有相同的key值就将值取出来再做精细比较并将new_obj里面的值干掉，new_obj剩下的就是要增加的，没找到的就是要删除的
                        obj = new_obj[key];
                        num = key;
                        delete new_obj[key];
                        break;
                    }
                }
                if(obj){  //有值就继续做精细比较
                    compareElm(oldVnode.children[i], obj);
                }else if(!is_text){  //删除没有的元素
                    let ele = Array.from(oldVnode.elm.children);  //将类数组变为数组
                    oldVnode.elm.removeChild(ele[num]);
                }
            }
            if(new_obj && JSON.stringify(new_obj) !== "{}"){  //还有剩下的就添加到对应的位置
                for(var key in new_obj){
                    if(Object.prototype.toString.call(new_obj[key]) !== "[object Object]"){  //将不是对象的（不是元素节点的）直接添加到元素中
                        oldVnode.elm.insertAdjacentHTML('beforeend',new_obj[key]);
                    }else{
                        let ele = Array.from(oldVnode.elm.children);  //将类数组变为数组
                        if(key == ele.length){  //防止e浏览器报错。当是最后一个的时候得是添加
                            isElement(oldVnode.elm, new_obj[key]);
                        }else{  //新增的时候
                            oldVnode.elm.insertBefore(createElement(new_obj[key]), ele[key]);
                        }
                    }
                    
                }
            }
            changeElm(oldVnode.elm, my_obj);  //改变子元素的位置
            oldVnode.children = newVnode.children;
        }
        return oldVnode;
    }else{  //暴力删除旧的，添加新的
        let parent = oldVnode.elm.parentNode;
        let new_ele = createElement(newVnode);
        parent.replaceChild(new_ele,oldVnode.elm);
        return newVnode;
    }
}
//elm为要改变子集顺序的父级dom元素， my_obj是新的newVnode按顺序得来的对象用来重新排序的
function changeElm(elm, my_obj){  //改变elm的位置
    let is_change = false;  //是否有改变位置
    let elm_arr = Array.from(elm.childNodes);   //子元素类数组变为数组
    if(elm_arr.length && my_obj && JSON.stringify(my_obj) !== "{}"){
        elm_arr.forEach((item,index)=>{
            if(my_obj[index] && Object.prototype.toString.call(my_obj[index]) !== "[object Object]"){  //不是对象
                for(var i=0;i<elm_arr.length;i++){
                    if(elm_arr[i].textContent == my_obj[index] && elm_arr[i].key === undefined && elm_arr[i].nodeName.toLowerCase()=="#text"){  //内容相等且没有key且只为文字不是元素加文字
                        elm.removeChild(elm_arr[i])  //删除以前的
                        item.insertAdjacentHTML('beforeBegin',my_obj[index]);  //将新的顺序提升上去
                        elm_arr.splice(i,1);  //使用了后就将自身数组里的干掉
                        delete my_obj[index];  //对象里的也要干掉
                        is_change = true;      //改变了
                    }
                }
            }else{  //是dom元素
                for(var key in my_obj){
                    if(my_obj[key].key == item.key && my_obj[key].sel == item.tagName.toLowerCase()){  //当元素名字和key一样时
                        if(index != key){
                            elm.insertBefore(item, elm_arr[key]);
                            is_change = true;
                        }
                    }
                }
            }
            
        })
    }
    if(is_change){  //如果有改变就继续递归，直到不需要换位为止
        changeElm(elm, my_obj)
    }
}
function isAlick(oldVnode,newVnode){  //判断2个节点是否完全一样
    if(oldVnode === newVnode){
        return true;
    }else if(Object.prototype.toString.call(oldVnode) != "[object Object]" || Object.prototype.toString.call(newVnode) != "[object Object]"){
        return false;
    }
    let my_bool = true;
    if(oldVnode.key !== newVnode.key){
        my_bool = false;
    }
    if(oldVnode.sel !== newVnode.sel){
        my_bool = false;
    }
    if(oldVnode.text !== newVnode.text){
        my_bool = false;
    }
    if(JSON.stringify(oldVnode.data) !== JSON.stringify(newVnode.data)){
        my_bool = false;
    }
    if(oldVnode.children && newVnode.children){  //如果有子集就递归判断子集是不是有不一样的
        oldVnode.children.forEach((item,index)=>{
            if(!isAlick(item, newVnode.children[index])){
                my_bool = false;
            }
        })
    }else if(oldVnode.children){
        my_bool = false;
    }else if(newVnode.children){
        my_bool = false;
    }
    return my_bool;
}
function createElement(vnode){ //创建元素
    let ele = document.createElement(vnode.sel);
    vnode.elm = ele;  //将自己这个创建的元素加入自己的对象中
    if(vnode.data){  //给标签加属性
        for(var key in vnode.data){ 
            addElementProps(ele, key, vnode.data[key])
        }
    }
    let {text, children} = vnode;
    if(text !== undefined && children !== undefined){  //这样的情况不会存在

    }else if(text !== undefined){
        ele.innerText = text;
    }else if(children !== undefined && children.length){  //有子元素就继续嵌套增加
        children.forEach(item => {
            isElement(ele, item);
        });
    }
    return ele;
}

function isElement(ele, value){  //添加子元素时判断其类型，是添加dom元素还是其他的
    if(Object.prototype.toString.call(value) !== "[object Object]"){  //将不是对象的（不是元素节点的）直接添加到元素中
        ele.insertAdjacentHTML('beforeend',value);
    }else{  //添加dom元素
        ele.appendChild(createElement(value));
    }
}

function addElementProps(obj ,key, value){  //给标签加属性，可以递归深入添加
    let str = Object.prototype.toString.call(value);
    if(key === 'on' && str === "[object Object]"){  //当是事件时就不走下面了
        for(var obj_key in value){
            obj.addEventListener(obj_key,value[obj_key]);
        }
    }else if( str === "[object Object]"){
        if(!obj[key]){
            obj[key] = value;
        }else{
            for(var i in value){
                addElementProps(obj[key], i, value[i]);
            }
        }
    }else if( str === "[object Array]"){
        if(!obj[key]){
            obj[key] = value;
        }else{
            for(var i=0;i<value.length;i++){
                addElementProps(obj[key], key.length,value[i]);
            }
        }
    }else{
        if(key.substr(0,5) == "data-"){  //设置私有属性
            obj.setAttribute(key,value);
        }else{
            obj[key] = value;
        }
    }
}